package org.NooLab.texx.tcp;

import java.util.Observable;
import java.util.Observer;



import org.NooLab.texx.tcp.box.TcpBox;
import org.NooLab.texx.tcp.box.agents.data.Data;
import org.NooLab.texx.tcp.box.agents.data.DataIntf;
import org.NooLab.texx.tcp.box.infra.DataReceiverIntf;
import org.NooLab.texx.tcp.box.infra.DataSenderIntf;
import org.NooLab.tikaserver.intf.TikaSrvDataTransferPkgIntf;
import org.NooLab.tikaserver.tcp.agents.TikaSrvCmdPkg;
import org.NooLab.utilities.logging.PrintLog;
import org.NooLab.utilities.net.GUID;
import org.NooLab.utilities.objects.StringedObjects;



public class TikaSrvClientAgent extends Observable{
   

	int senderPort ; 
	int listeningPort ;
	
	TcpBox tcpBox;
	Observer tscObserver;
	
	DataReceiverIntf receiverDevice;
	DataSenderIntf senderDevice;
	
	MessageReceiver msgReceiver;

	TikaDeliveryQueue deliveryQueue;
	
	StringedObjects sob = new StringedObjects();
	PrintLog out = new PrintLog(3,true);
	
	private boolean sent;
	private int silentShutDown;
	
	// ========================================================================
	public TikaSrvClientAgent( TikaServerConnection parent, int listenPort, int sendPort) {
		 
		deliveryQueue = parent.tikaDeliveryQueue ;
		
		tscObserver = (Observer)parent; // TikaServerConnection
		addObserver(tscObserver);
		
		
		
		senderPort = sendPort;
		listeningPort = listenPort ;
	
		tcpBox = new TcpBox();
		
		
		msgReceiver = new MessageReceiver(); 
		
		init( );
	}
	// ========================================================================
	
	
	private void init( ) {
		
		
		receiverDevice = tcpBox.createReceiver(listeningPort, senderPort, msgReceiver, "") ;
		senderDevice   = tcpBox.createSender(senderPort, listeningPort, "") ;
		
		// testLoop(1) ;
	}
	
	public void close(){
		close(0);
	}
		
	public void close(int silent){
		try{
			this.deleteObserver(tscObserver);
	
		}catch(Exception e){}

		
		try{
			
			silentShutDown = silent ;
			
			receiverDevice.setSilentShutDown(silentShutDown) ;
			senderDevice.setSilentShutDown(silentShutDown) ;
			
			
			receiverDevice.closePort();
			senderDevice.release();
			tcpBox.deleteObservers();
			
			out.delay(200);
			receiverDevice= null;
			senderDevice = null;
			
		}catch(Exception e){}

		silentShutDown=0;
	}
	
	public String send(String str){
		String suid = GUID.randomvalue() ;
		
		out.delay(2);
		sent = false ;
		
		new SenderEvent(str,suid);
		if (senderDevice.getLastSenderState()<0){
			out.printErr(1, "Error while attempting to send : code = " + senderDevice.getLastSenderState() );
			suid="-1";
		}
		
		while (sent==false){
			out.delay(2);
		}
		return suid;
	}
	
	
	class SenderEvent implements Runnable{
		Thread sndThrd;
		String str="",suid="";
		
		public SenderEvent(String str, String suid) {
			
			this.str= str;
			this.suid= suid;
			sndThrd = new Thread (this,"sndThrd");

			sndThrd.start();
		}

		@Override
		public void run() {

			senderDevice.send(str,suid);
			sent=true;
		}
		
	}

	private void testLoop(int n) {
		DataIntf data;
		String suid;
		
		for (int i=0;i<n;i++){
			data = new Data(i+1);
			suid = GUID.randomvalue() ;
			
			// here we send the data using an external GUID,
			// of course, the GUID could also be part of the data object itself
			out.print(2, "C sending "+(i+1)+"  with id <"+suid+">");
			String pmsg = sob.encode(data);
			
			senderDevice.send( pmsg,suid );
			
			out.delay(500);
		}
	}


	class MessageReceiver implements Observer{

		@Override
		public void update(Observable srv, Object dataObj) {
		 	
			String guid ;
			int confcode;
			String[] dataPkg;
			dataPkg = (String[])dataObj ;
			
			TikaSrvDataTransferPkgIntf data=null; 
			
			
			
			out.print(4, "C: "+srv.toString().replace("org.NooLab.", "")) ;
			
			Object obj = sob.decode( (String)dataPkg[1]);
			
			if (obj instanceof TikaSrvCmdPkg){
				out.print(3, "C: ping response (or sth similar) received from server...") ;
				return;
			}
			if (obj instanceof TikaSrvDataTransferPkgIntf){
			 
				data = (TikaSrvDataTransferPkgIntf)obj ;
			}
			if (data==null){
				return;
			}
			
			confcode = data.getConfirmationCode();
			guid = data.getGuid();
			
			deliveryQueue.updateStatusByGuid(guid, confcode) ;
			
			
			try{

				int txtLen = -1;
				if (data.getResultText()!=null){
					txtLen = data.getResultText().length();
				}
				out.print(3,"texx tikasrv-client received changed data for id <"+dataPkg[0]+"> \n"+
					    	"          returned package will be routed to TSC, confirmation code = "+
					    	data.getConfirmationCode()+" ,  L = "+txtLen );

			}catch(Exception e){
				
			}
			
			
			setChanged();
			notifyObservers( data ) ; // -> TikaServerConnection
			
		}
		
	}
	
}